package com.chianghao.rockframewrok.core.mybatis.sql;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.chianghao.rockframewrok.core.lambda.IGetter;
import com.chianghao.rockframewrok.core.mybatis.sql.db_enum.SpecialValue;
import com.chianghao.rockframewrok.core.mybatis.sql.db_enum.SqlConnector;
import com.chianghao.rockframewrok.core.mybatis.sql.db_enum.SqlOperators;
import com.chianghao.rockframewrok.core.mybatis.sql.db_enum.SqlOrderType;
import com.chianghao.rockframewrok.core.utils.ClassUtils;

public class SqlWrapper {

	List<SqlCondition> sqlWhereList;
	
	Set<String> fieldNames;
	
	Map<String,Object> params;
	
	SqlOrder sqlOrder;
	
	public SqlWrapper() {
		sqlWhereList = new ArrayList<SqlCondition>();
		params = new HashMap<String,Object>();
		fieldNames = new HashSet<>();
		sqlOrder = new SqlOrder();
	}
	
	public String[] getFieldNames() {
		String[] array = fieldNames.toArray(new String[fieldNames.size()]);
		return array;
	}

	
	@SuppressWarnings("unchecked")
	public <T> SqlWrapper addFields(IGetter<T> ...fns) {
		if(fns==null) {
			throw new IllegalArgumentException("SqlWrapper，addfields,fns不能为空");
		}
		
		String[] array = new String[fns.length];
		for(int i=0;i<fns.length;i++) {
			array[i] = ClassUtils.convertToFieldName(fns[i]);
		}
		return addFields(array);
	}
	
	
	private SqlWrapper addFields(String... fields) {
		for(String field:fields) {
			fieldNames.add(field);
		}
		return this;
	}
	
	public <T>  SqlWrapper order(IGetter<T> fn,SqlOrderType type) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		return this.order(fieldName,type);
	}
	
	
	
	public Map<String, Object> getParams() {
		return params;
	}
	public void setParams(Map<String, Object> params) {
		this.params = params;
	}
	
	public SqlWrapper and() {
		sqlWhereList.add(new SqlCondition(SqlConnector.and));
		return this;
	}
	
	public SqlWrapper start() {
		sqlWhereList.add(new SqlCondition(SqlConnector.start));
		return this;
	}
	
	public SqlWrapper andStart() {
		sqlWhereList.add(new SqlCondition(SqlConnector.andStart));
		return this;
	}

	public SqlWrapper or() {
		sqlWhereList.add(new SqlCondition(SqlConnector.or));
		return this;
	}

	public SqlWrapper orStart() {
		sqlWhereList.add(new SqlCondition(SqlConnector.orStart));
		return this;
	}

	public SqlWrapper end() {
		sqlWhereList.add(new SqlCondition(SqlConnector.end));
		return this;
	}

	public List<SqlCondition> getSqlWhereList() {
		return sqlWhereList;
	}

	public void setSqlWhereList(List<SqlCondition> sqlWhereList) {
		this.sqlWhereList = sqlWhereList;
	}

	public SqlOrder getSqlOrder() {
		return sqlOrder;
	}

	
	
	
	public <T> SqlWrapper isNull(IGetter<T> fn) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		sqlWhereList.add(new SqlCondition(fieldName,SqlOperators.equals,SpecialValue.Null));
		return this;
	}

	public <T> SqlWrapper isNotNull(IGetter<T> fn) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		sqlWhereList.add(new SqlCondition(fieldName,SqlOperators.not_equals,SpecialValue.Null));
		return this;
	}
	
	public <T> SqlWrapper addCondition(IGetter<T> fn, Object value) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		sqlWhereList.add(new SqlCondition(fieldName,value));
		params.put(fieldName, value);
		return this;
	}
	
	public <T> SqlWrapper addCondition(IGetter<T> fn, SqlOperators operators,Object value) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		sqlWhereList.add(new SqlCondition(fieldName,operators,value));
		params.put(fieldName, value);
		return this;
	}

	public <T> SqlWrapper addCondition(IGetter<T> fn, SqlOperators operators,Object[] value) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		sqlWhereList.add(new SqlCondition(fieldName,operators,value));
		params.put(fieldName, value);
		return this;
	}
	
	public <T> SqlWrapper addInCondition(IGetter<T> fn, List<? extends Object> values) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		Object[] valueArray = values.toArray(new Object[values.size()]);
		return addCondition(fieldName,SqlOperators.in,valueArray);
	}
	
	public <T> SqlWrapper addNotInCondition(IGetter<T> fn, List<? extends Object> values) {
		String fieldName = ClassUtils.convertToFieldName(fn);
		Object[] valueArray = values.toArray(new Object[values.size()]);
		return addCondition(fieldName,SqlOperators.not_in,valueArray);
	}
	
	private SqlWrapper addCondition(String fieldName, SqlOperators operators,Object[] value) {
		sqlWhereList.add(new SqlCondition(fieldName,operators,value));
		params.put(fieldName, value);
		return this;
	}
	
	private SqlWrapper order(String fieldName,SqlOrderType type) {
		if(StringUtils.isEmpty(fieldName)) {
			return this;
		}
		this.sqlOrder.add(fieldName, type);
		return this;
	}
	
	public SqlWrapper addCondition(String fieldName, Object value) {
		sqlWhereList.add(new SqlCondition(fieldName,value));
		params.put(fieldName, value);
		return this;
	}
//	
//	private SqlWrapper addCondition(String fieldName, SqlOperators operators,Object value) {
//		sqlWhereList.add(new SqlCondition(fieldName,operators,value));
//		params.put(fieldName, value);
//		return this;
//	}
//	
//	
//	private SqlWrapper addInCondition(String fieldName, List<? extends Object> values) {
//		Object[] valueArray = values.toArray(new Object[values.size()]);
//		return addCondition(fieldName,SqlOperators.in,valueArray);
//	}
//	
//	private SqlWrapper addNotInCondition(String fieldName, List<? extends Object> values) {
//		Object[] valueArray = values.toArray(new Object[values.size()]);
//		return addCondition(fieldName,SqlOperators.not_in,valueArray);
//	}
	
	
	
}
